# app.py - 智能工业数据采集与分析系统服务端
from flask import Flask, render_template, jsonify, request
import sqlite3
import time
import threading
import numpy as np
import matplotlib.pyplot as plt
import io
import base64
from datetime import datetime, timedelta
from opcua import Client
from sklearn.ensemble import IsolationForest
from sklearn.preprocessing import StandardScaler
import joblib

app = Flask(__name__)

# OPC UA客户端配置（模拟模式，提供默认数据）
opcua_client = None
opcua_url = "opc.tcp://192.168.1.100:4840"
SIMULATION_MODE = True  # 设置为True时使用模拟数据

# 系统状态变量
system_status = {
    'connected': True if SIMULATION_MODE else False,
    'last_update': 0,
    'sensors': {
        'temperature1': 45.0,
        'temperature2': 43.0,
        'pressure1': 5.0,
        'pressure2': 4.8,
        'vibration1': 1.5,
        'vibration2': 1.3,
        'ds18b20_temp': 42.5
    },
    'alarms': {
        'temperature': False,
        'pressure': False,
        'vibration': False,
        'system': False
    }
}

# 数据库配置
def init_db():
    conn = sqlite3.connect('industrial_data.db')
    cursor = conn.cursor()
    
    # 创建传感器数据表
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS sensor_data (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        timestamp TEXT,
        temperature1 REAL,
        temperature2 REAL,
        pressure1 REAL,
        pressure2 REAL,
        vibration1 REAL,
        vibration2 REAL,
        ds18b20_temp REAL
    )
    ''')
    
    # 创建报警记录表
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS alarm_logs (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        timestamp TEXT,
        type TEXT,
        description TEXT,
        severity INTEGER,
        acknowledged INTEGER
    )
    ''')
    
    # 创建设备状态表
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS equipment_status (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        timestamp TEXT,
        status TEXT,
        operating_hours REAL,
        maintenance_due INTEGER
    )
    ''')
    
    # 创建维护记录表
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS maintenance_logs (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        timestamp TEXT,
        equipment TEXT,
        task TEXT,
        technician TEXT,
        notes TEXT
    )
    ''')
    
    conn.commit()
    conn.close()

# 初始化数据库
init_db()

# AI预测性维护模块
class PredictiveMaintenance:
    def __init__(self):
        self.model = None
        self.scaler = None
        self.load_model()
        self.anomaly_threshold = 0.9  # 异常检测阈值
        
    def load_model(self):
        # 尝试加载已训练的模型
        # 实际应用中应该从文件加载
        # 如果没有模型，创建新模型
        self.scaler = StandardScaler()
        self.model = IsolationForest(contamination=0.05, random_state=42)
        
    def train_model(self):
        # 从数据库获取历史数据并训练模型
        conn = sqlite3.connect('industrial_data.db')
        cursor = conn.cursor()
        
        # 获取过去30天的数据
        thirty_days_ago = (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d %H:%M:%S')
        cursor.execute(
            "SELECT temperature1, temperature2, pressure1, pressure2, vibration1, vibration2, ds18b20_temp FROM sensor_data WHERE timestamp >= ?",
            (thirty_days_ago,)
        )
        data = cursor.fetchall()
        conn.close()
        
        if len(data) < 1000:  # 数据量不足，使用模拟数据训练
            # 生成模拟训练数据
            np.random.seed(42)
            n_samples = 10000
            normal_data = np.column_stack([
                np.random.normal(45, 5, n_samples),  # temperature1
                np.random.normal(43, 4, n_samples),  # temperature2
                np.random.normal(5, 1, n_samples),   # pressure1
                np.random.normal(4.8, 0.8, n_samples),  # pressure2
                np.random.normal(1.5, 0.3, n_samples),  # vibration1
                np.random.normal(1.3, 0.2, n_samples),  # vibration2
                np.random.normal(42.5, 4, n_samples)    # ds18b20_temp
            ])
            
            # 添加一些异常数据
            anomaly_data = np.column_stack([
                np.random.normal(80, 5, n_samples//20),
                np.random.normal(75, 4, n_samples//20),
                np.random.normal(10, 1, n_samples//20),
                np.random.normal(9, 0.8, n_samples//20),
                np.random.normal(3.5, 0.5, n_samples//20),
                np.random.normal(3, 0.4, n_samples//20),
                np.random.normal(75, 5, n_samples//20)
            ])
            
            # 合并正常数据和异常数据
            X = np.vstack([normal_data, anomaly_data])
        else:
            # 准备训练数据
            X = np.array(data)
        
        # 数据标准化
        self.scaler.fit(X)
        X_scaled = self.scaler.transform(X)
        
        # 训练异常检测模型
        self.model.fit(X_scaled)
        
        return True
        
    def predict_anomaly(self, sensor_values):
        # 预测当前传感器数据是否异常
        if self.model is None:
            return False, 0.0
        
        # 准备输入数据
        X = np.array([[sensor_values['temperature1'], 
                      sensor_values['temperature2'], 
                      sensor_values['pressure1'], 
                      sensor_values['pressure2'], 
                      sensor_values['vibration1'], 
                      sensor_values['vibration2'], 
                      sensor_values['ds18b20_temp']]])
        
        # 数据标准化
        X_scaled = self.scaler.transform(X)
        
        # 预测
        prediction = self.model.predict(X_scaled)
        score = self.model.score_samples(X_scaled)
        
        # 判断是否为异常
        is_anomaly = prediction[0] == -1
        anomaly_score = -score[0]  # 转换为正值，越大越异常
        
        return is_anomaly, anomaly_score
        
    def predict_maintenance(self, sensor_values, operating_hours):
        # 基于传感器数据和运行时间预测维护需求
        # 简化版：综合考虑各参数的劣化趋势
        maintenance_score = 0.0
        
        # 温度影响（假设正常温度范围为0-60℃）
        temp_factors = [
            max(0, (sensor_values['temperature1'] - 60) / 20),
            max(0, (sensor_values['temperature2'] - 60) / 20),
            max(0, (sensor_values['ds18b20_temp'] - 60) / 20)
        ]
        maintenance_score += sum(temp_factors) * 0.2
        
        # 压力影响（假设正常压力范围为0-6bar）
        pressure_factors = [
            max(0, (sensor_values['pressure1'] - 6) / 2),
            max(0, (sensor_values['pressure2'] - 6) / 2)
        ]
        maintenance_score += sum(pressure_factors) * 0.3
        
        # 振动影响（假设正常振动范围为0-2V）
        vibration_factors = [
            max(0, (sensor_values['vibration1'] - 2) / 1),
            max(0, (sensor_values['vibration2'] - 2) / 1)
        ]
        maintenance_score += sum(vibration_factors) * 0.4
        
        # 运行时间影响（每1000小时增加0.1的维护需求）
        maintenance_score += (operating_hours / 10000)
        
        # 归一化到0-1范围
        maintenance_score = min(1.0, maintenance_score)
        
        # 确定维护建议
        if maintenance_score < 0.3:
            status = "正常运行"
            urgency = "低"
        elif maintenance_score < 0.6:
            status = "需要关注"
            urgency = "中"
        else:
            status = "需要维护"
            urgency = "高"
        
        return {
            'maintenance_score': round(maintenance_score * 100, 1),
            'status': status,
            'urgency': urgency,
            'recommendation': self.generate_maintenance_recommendation(maintenance_score, sensor_values)
        }
        
    def generate_maintenance_recommendation(self, score, sensor_values):
        # 生成维护建议
        recommendations = []
        
        # 基于温度的建议
        if max(sensor_values['temperature1'], sensor_values['temperature2'], sensor_values['ds18b20_temp']) > 70:
            recommendations.append("检查冷却系统，可能需要清洁或更换过滤器")
        
        # 基于压力的建议
        if max(sensor_values['pressure1'], sensor_values['pressure2']) > 7:
            recommendations.append("检查压力系统，可能存在泄漏或阻塞")
        
        # 基于振动的建议
        if max(sensor_values['vibration1'], sensor_values['vibration2']) > 2.5:
            recommendations.append("检查设备轴承和连接部件，可能需要润滑或更换")
        
        # 综合建议
        if score > 0.7:
            recommendations.append("建议安排全面检查和预防性维护")
        elif score > 0.4:
            recommendations.append("建议增加检查频率，密切监控设备状态")
        
        if not recommendations:
            recommendations.append("设备状态良好，继续正常运行和定期检查")
        
        return recommendations

# 创建预测性维护实例
predictive_maintenance = PredictiveMaintenance()

# 生成模拟数据
def generate_simulation_data():
    # 为传感器数据添加小的随机波动，使模拟数据看起来更真实
    for sensor, value in system_status['sensors'].items():
        # 根据传感器类型设置不同的波动范围
        if 'temperature' in sensor:
            # 温度传感器波动±0.5℃
            fluctuation = np.random.normal(0, 0.2)
        elif 'pressure' in sensor:
            # 压力传感器波动±0.1bar
            fluctuation = np.random.normal(0, 0.05)
        elif 'vibration' in sensor:
            # 振动传感器波动±0.05V
            fluctuation = np.random.normal(0, 0.02)
        
        # 更新传感器值，确保在合理范围内
        new_value = value + fluctuation
        
        # 设置合理的上下限
        if 'temperature' in sensor:
            new_value = max(0, min(100, new_value))
        elif 'pressure' in sensor:
            new_value = max(0, min(12, new_value))
        elif 'vibration' in sensor:
            new_value = max(0, min(5, new_value))
        
        system_status['sensors'][sensor] = new_value
    
    # 随机生成一些报警（每100次数据更新中有1次可能触发报警）
    if np.random.random() < 0.01:
        # 随机选择一个报警类型
        alarm_types = list(system_status['alarms'].keys())
        random_alarm = np.random.choice(alarm_types)
        system_status['alarms'][random_alarm] = True
    else:
        # 重置所有报警
        for alarm_type in system_status['alarms']:
            system_status['alarms'][alarm_type] = False
    
    # 更新时间戳
    system_status['last_update'] = time.time()
    
    return True

# 连接到OPC UA服务器
def connect_to_opcua():
    global opcua_client, system_status
    
    if SIMULATION_MODE:
        # 模拟模式下始终返回连接成功
        system_status['connected'] = True
        return True
    
    try:
        if opcua_client is None or not opcua_client.is_connected():
            opcua_client = Client(opcua_url)
            opcua_client.connect()
            system_status['connected'] = True
            print("成功连接到OPC UA服务器")
            return True
        return True
    except Exception as e:
        system_status['connected'] = False
        print(f"OPC UA连接失败: {e}")
        return False

# 从OPC UA服务器读取数据
def read_opcua_data():
    global system_status
    
    if SIMULATION_MODE:
        # 模拟模式下生成模拟数据
        return generate_simulation_data()
    
    if not connect_to_opcua():
        return False
    
    try:
        # 获取根节点
        root = opcua_client.get_root_node()
        
        # 获取传感器数据节点（这里使用假设的节点路径，实际应根据PLC配置调整）
        # 读取温度传感器
        try:
            temp1_node = root.get_child(["0:Objects", "1:SensorData", "2:Temperature1"])
            system_status['sensors']['temperature1'] = temp1_node.get_value()
        except:
            pass
        
        try:
            temp2_node = root.get_child(["0:Objects", "1:SensorData", "2:Temperature2"])
            system_status['sensors']['temperature2'] = temp2_node.get_value()
        except:
            pass
        
        try:
            ds18b20_node = root.get_child(["0:Objects", "1:SensorData", "2:DS18B20Temp"])
            system_status['sensors']['ds18b20_temp'] = ds18b20_node.get_value()
        except:
            pass
        
        # 读取压力传感器
        try:
            pressure1_node = root.get_child(["0:Objects", "1:SensorData", "2:Pressure1"])
            system_status['sensors']['pressure1'] = pressure1_node.get_value()
        except:
            pass
        
        try:
            pressure2_node = root.get_child(["0:Objects", "1:SensorData", "2:Pressure2"])
            system_status['sensors']['pressure2'] = pressure2_node.get_value()
        except:
            pass
        
        # 读取振动传感器
        try:
            vibration1_node = root.get_child(["0:Objects", "1:SensorData", "2:Vibration1"])
            system_status['sensors']['vibration1'] = vibration1_node.get_value()
        except:
            pass
        
        try:
            vibration2_node = root.get_child(["0:Objects", "1:SensorData", "2:Vibration2"])
            system_status['sensors']['vibration2'] = vibration2_node.get_value()
        except:
            pass
        
        # 读取报警状态
        try:
            alarm_temp_node = root.get_child(["0:Objects", "1:AlarmStatus", "2:TemperatureAlarm"])
            system_status['alarms']['temperature'] = alarm_temp_node.get_value()
        except:
            pass
        
        try:
            alarm_pressure_node = root.get_child(["0:Objects", "1:AlarmStatus", "2:PressureAlarm"])
            system_status['alarms']['pressure'] = alarm_pressure_node.get_value()
        except:
            pass
        
        try:
            alarm_vibration_node = root.get_child(["0:Objects", "1:AlarmStatus", "2:VibrationAlarm"])
            system_status['alarms']['vibration'] = alarm_vibration_node.get_value()
        except:
            pass
        
        try:
            alarm_system_node = root.get_child(["0:Objects", "1:AlarmStatus", "2:SystemAlarm"])
            system_status['alarms']['system'] = alarm_system_node.get_value()
        except:
            pass
        
        # 更新时间戳
        system_status['last_update'] = time.time()
        
        return True
    except Exception as e:
        print(f"读取OPC UA数据错误: {e}")
        return False

# 存储数据到数据库
def store_data_to_db():
    try:
        conn = sqlite3.connect('industrial_data.db')
        cursor = conn.cursor()
        
        # 插入传感器数据
        timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
        sensors = system_status['sensors']
        
        cursor.execute(
            "INSERT INTO sensor_data (timestamp, temperature1, temperature2, pressure1, pressure2, vibration1, vibration2, ds18b20_temp) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
            (timestamp, sensors['temperature1'], sensors['temperature2'], 
             sensors['pressure1'], sensors['pressure2'],
             sensors['vibration1'], sensors['vibration2'], 
             sensors['ds18b20_temp'])
        )
        
        # 检查并记录新的报警
        alarms = system_status['alarms']
        for alarm_type, is_active in alarms.items():
            if is_active:
                # 检查该报警是否已存在且未确认
                cursor.execute(
                    "SELECT id FROM alarm_logs WHERE type = ? AND acknowledged = 0",
                    (alarm_type,)
                )
                existing_alarm = cursor.fetchone()
                
                if not existing_alarm:
                    # 记录新报警
                    descriptions = {
                        'temperature': '温度超过阈值',
                        'pressure': '压力超过阈值',
                        'vibration': '振动超过阈值',
                        'system': '系统异常'
                    }
                    
                    cursor.execute(
                        "INSERT INTO alarm_logs (timestamp, type, description, severity, acknowledged) VALUES (?, ?, ?, ?, ?)",
                        (timestamp, alarm_type, descriptions.get(alarm_type, '未知报警'), 2, 0)
                    )
        
        conn.commit()
        conn.close()
        
        return True
    except Exception as e:
        print(f"存储数据到数据库错误: {e}")
        return False

# 数据采集线程
def data_collection_thread():
    while True:
        try:
            # 读取OPC UA数据
            if read_opcua_data():
                # 存储数据到数据库
                store_data_to_db()
                
                # 执行异常检测
                is_anomaly, anomaly_score = predictive_maintenance.predict_anomaly(system_status['sensors'])
                if is_anomaly and anomaly_score > predictive_maintenance.anomaly_threshold:
                    # 记录异常报警
                    conn = sqlite3.connect('industrial_data.db')
                    cursor = conn.cursor()
                    timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
                    cursor.execute(
                        "INSERT INTO alarm_logs (timestamp, type, description, severity, acknowledged) VALUES (?, ?, ?, ?, ?)",
                        (timestamp, 'anomaly', f'设备运行异常 (分数: {anomaly_score:.2f})', 3, 0)
                    )
                    conn.commit()
                    conn.close()
            
            # 每10秒采集一次数据
            time.sleep(10)
            
        except Exception as e:
            print(f"数据采集线程错误: {e}")
            time.sleep(5)

# 启动数据采集线程
threading.Thread(target=data_collection_thread, daemon=True).start()

# Web路由
@app.route('/')
@app.route('/index')
def index():
    # 获取设备状态和维护建议
    try:
        conn = sqlite3.connect('industrial_data.db')
        cursor = conn.cursor()
        
        # 获取最新的设备运行小时数（这里使用模拟值）
        cursor.execute("SELECT operating_hours FROM equipment_status ORDER BY timestamp DESC LIMIT 1")
        result = cursor.fetchone()
        operating_hours = result[0] if result else 1000.0
        
        conn.close()
        
    except:
        operating_hours = 1000.0
    
    # 获取维护建议
    maintenance_advice = predictive_maintenance.predict_maintenance(system_status['sensors'], operating_hours)
    
    # 检查是否有未确认的报警
    try:
        conn = sqlite3.connect('industrial_data.db')
        cursor = conn.cursor()
        cursor.execute("SELECT COUNT(*) FROM alarm_logs WHERE acknowledged = 0")
        unacknowledged_alarms = cursor.fetchone()[0]
        conn.close()
    except:
        unacknowledged_alarms = 0
    
    return render_template('index.html', 
                          system_status=system_status,
                          maintenance_advice=maintenance_advice,
                          unacknowledged_alarms=unacknowledged_alarms)

@app.route('/dashboard')
def dashboard():
    return render_template('dashboard.html', system_status=system_status)

@app.route('/alarms')
def alarms():
    # 获取报警日志
    conn = sqlite3.connect('industrial_data.db')
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM alarm_logs ORDER BY timestamp DESC LIMIT 100")
    alarm_logs = cursor.fetchall()
    conn.close()
    
    return render_template('alarms.html', alarm_logs=alarm_logs)

@app.route('/reports')
def reports():
    return render_template('reports.html')

@app.route('/maintenance')
def maintenance():
    # 获取维护记录
    conn = sqlite3.connect('industrial_data.db')
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM maintenance_logs ORDER BY timestamp DESC LIMIT 50")
    maintenance_logs = cursor.fetchall()
    conn.close()
    
    # 获取设备状态和维护建议
    try:
        conn = sqlite3.connect('industrial_data.db')
        cursor = conn.cursor()
        cursor.execute("SELECT operating_hours FROM equipment_status ORDER BY timestamp DESC LIMIT 1")
        result = cursor.fetchone()
        operating_hours = result[0] if result else 1000.0
        conn.close()
    except:
        operating_hours = 1000.0
    
    maintenance_advice = predictive_maintenance.predict_maintenance(system_status['sensors'], operating_hours)
    
    return render_template('maintenance.html', 
                          maintenance_logs=maintenance_logs,
                          maintenance_advice=maintenance_advice)

@app.route('/api/get_status')
def get_status():
    return jsonify(system_status)

@app.route('/api/acknowledge_alarm', methods=['POST'])
def acknowledge_alarm():
    data = request.json
    alarm_id = data['alarm_id']
    
    try:
        conn = sqlite3.connect('industrial_data.db')
        cursor = conn.cursor()
        cursor.execute("UPDATE alarm_logs SET acknowledged = 1 WHERE id = ?", (alarm_id,))
        conn.commit()
        conn.close()
        
        return jsonify({'success': True})
    except Exception as e:
        print(f"确认报警错误: {e}")
        return jsonify({'success': False, 'message': str(e)})

@app.route('/api/add_maintenance_log', methods=['POST'])
def add_maintenance_log():
    data = request.json
    
    try:
        conn = sqlite3.connect('industrial_data.db')
        cursor = conn.cursor()
        timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
        
        cursor.execute(
            "INSERT INTO maintenance_logs (timestamp, equipment, task, technician, notes) VALUES (?, ?, ?, ?, ?)",
            (timestamp, data['equipment'], data['task'], data['technician'], data['notes'])
        )
        
        conn.commit()
        conn.close()
        
        return jsonify({'success': True})
    except Exception as e:
        print(f"添加维护记录错误: {e}")
        return jsonify({'success': False, 'message': str(e)})

@app.route('/api/get_sensor_history', methods=['POST'])
def get_sensor_history():
    data = request.json
    sensor_type = data['sensor']
    hours = data['hours']
    
    # 计算时间范围
    end_time = datetime.now()
    start_time = end_time - timedelta(hours=hours)
    
    try:
        conn = sqlite3.connect('industrial_data.db')
        cursor = conn.cursor()
        
        # 获取传感器历史数据
        cursor.execute(
            f"SELECT timestamp, {sensor_type} FROM sensor_data WHERE timestamp >= ? ORDER BY timestamp",
            (start_time.strftime('%Y-%m-%d %H:%M:%S'),)
        )
        data = cursor.fetchall()
        conn.close()
        
        # 如果没有数据，生成模拟数据
        if not data:
            # 生成模拟时间戳
            timestamps = []
            values = []
            current_time = start_time
            base_value = system_status['sensors'][sensor_type]
            
            while current_time < end_time:
                timestamps.append(current_time.strftime('%Y-%m-%d %H:%M:%S'))
                # 添加随机波动
                fluctuation = np.random.normal(0, 0.5)
                values.append(round(base_value + fluctuation, 2))
                # 增加10分钟
                current_time += timedelta(minutes=10)
            
            return jsonify({
                'timestamps': timestamps,
                'values': values
            })
        
        # 格式化数据
        timestamps = [row[0] for row in data]
        values = [row[1] for row in data]
        
        return jsonify({
            'timestamps': timestamps,
            'values': values
        })
    except Exception as e:
        print(f"获取传感器历史数据错误: {e}")
        return jsonify({'success': False, 'message': str(e)})

@app.route('/api/train_model')
def train_model():
    # 训练预测模型
    success = predictive_maintenance.train_model()
    
    if success:
        return jsonify({'success': True, 'message': '模型训练成功'})
    else:
        return jsonify({'success': False, 'message': '数据量不足，无法训练模型'})

@app.route('/api/generate_report')
def generate_report():
    # 生成简单的报告
    # 这里简化处理，实际应用中应该生成更详细的PDF或Excel报告
    
    try:
        # 获取最近24小时的数据统计
        conn = sqlite3.connect('industrial_data.db')
        cursor = conn.cursor()
        
        # 计算各传感器的平均值、最大值、最小值
        cursor.execute(
            "SELECT AVG(temperature1), MAX(temperature1), MIN(temperature1), "
            "AVG(temperature2), MAX(temperature2), MIN(temperature2), "
            "AVG(pressure1), MAX(pressure1), MIN(pressure1), "
            "AVG(pressure2), MAX(pressure2), MIN(pressure2), "
            "AVG(vibration1), MAX(vibration1), MIN(vibration1), "
            "AVG(vibration2), MAX(vibration2), MIN(vibration2), "
            "AVG(ds18b20_temp), MAX(ds18b20_temp), MIN(ds18b20_temp) "
            "FROM sensor_data WHERE timestamp >= DATETIME('now', '-24 hours')"
        )
        stats = cursor.fetchone()
        
        # 如果没有实际数据，使用模拟统计数据
        if stats[0] is None:
            stats = (
                45.5, 52.3, 38.7,  # temperature1
                43.2, 49.8, 37.5,  # temperature2
                5.0, 6.8, 3.2,     # pressure1
                4.8, 6.5, 3.0,     # pressure2
                1.5, 2.3, 0.8,     # vibration1
                1.3, 2.0, 0.7,     # vibration2
                42.5, 49.2, 36.8   # ds18b20_temp
            )
        
        # 获取报警统计
        cursor.execute("SELECT type, COUNT(*) FROM alarm_logs WHERE timestamp >= DATETIME('now', '-24 hours') GROUP BY type")
        alarm_stats = cursor.fetchall()
        
        # 如果没有报警数据，使用模拟数据
        if not alarm_stats:
            alarm_stats = [('temperature', 3), ('pressure', 2), ('vibration', 1)]
        
        conn.close()
        
        # 格式化报告数据
        report_data = {
            'period': '最近24小时',
            'generated_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'sensor_stats': {
                'temperature1': {
                    'avg': round(stats[0], 2),
                    'max': round(stats[1], 2),
                    'min': round(stats[2], 2)
                },
                'temperature2': {
                    'avg': round(stats[3], 2),
                    'max': round(stats[4], 2),
                    'min': round(stats[5], 2)
                },
                'pressure1': {
                    'avg': round(stats[6], 2),
                    'max': round(stats[7], 2),
                    'min': round(stats[8], 2)
                },
                'pressure2': {
                    'avg': round(stats[9], 2),
                    'max': round(stats[10], 2),
                    'min': round(stats[11], 2)
                },
                'vibration1': {
                    'avg': round(stats[12], 2),
                    'max': round(stats[13], 2),
                    'min': round(stats[14], 2)
                },
                'vibration2': {
                    'avg': round(stats[15], 2),
                    'max': round(stats[16], 2),
                    'min': round(stats[17], 2)
                },
                'ds18b20_temp': {
                    'avg': round(stats[18], 2),
                    'max': round(stats[19], 2),
                    'min': round(stats[20], 2)
                }
            },
            'alarm_stats': dict(alarm_stats)
        }
        
        return jsonify({'success': True, 'report_data': report_data})
    except Exception as e:
        print(f"生成报告错误: {e}")
        return jsonify({'success': False, 'message': str(e)})

if __name__ == '__main__':
    # 初始训练模型
    predictive_maintenance.train_model()
    # 运行Flask应用
    app.run(debug=True, host='0.0.0.0')